#include "packet.h"

//===============================================================
// Initializes a packet of the specified size.
//===============================================================
CPacket::CPacket(const char *pData, u_int nLen) : m_nSize(nLen), m_nPos(0)
{
	m_pData = (char *)malloc(nLen);
	memcpy(m_pData, pData, nLen);
}

//===============================================================
// Initializes a empty packet of the specified size.
//===============================================================
CPacket::CPacket(u_int nLen) : m_nSize(nLen), m_nPos(0)
{
	m_pData = (char *)malloc(nLen);
	memset(m_pData, 0, nLen);
}

//===============================================================
// Releases the buffer allocated by the packet.
//===============================================================
CPacket::~CPacket()
{
	if (m_pData)
		free(m_pData);
}

//===============================================================
// Writes a single byte to the packet.
//===============================================================
void CPacket::Write(u_char nValue)
{
	m_pData[m_nPos] = nValue;
	m_nPos++;
}

//===============================================================
// Writes a short integer to the packet.
//===============================================================
void CPacket::Write(u_short nValue)
{
	m_pData[m_nPos]     = ((nValue & 0xFF00) >> 8);
	m_pData[m_nPos + 1] = ((nValue & 0x00FF));
	m_nPos += 2;
}

//===============================================================
// Writes a integer to the packet.
//===============================================================
void CPacket::Write(u_int nValue)
{
	m_pData[m_nPos]     = ((nValue & 0xFF000000) >> 24);
	m_pData[m_nPos + 1] = ((nValue & 0x00FF0000) >> 16);
	m_pData[m_nPos + 2] = ((nValue & 0x0000FF00) >> 8);
	m_pData[m_nPos + 3] = ((nValue & 0x000000FF));
	m_nPos += 4;
}

//===============================================================
// Writes the specified data to the packet.
//===============================================================
void CPacket::Write(const char *pData, u_int nLen)
{
	if (nLen == 0)
		return;

	memcpy(m_pData + m_nPos, pData, nLen);
	m_nPos += nLen;
}

//===============================================================
// Writes a string to the packet.
//===============================================================
void CPacket::Write(const char *szText)
{
	u_int nLen = strlen(szText);
	Write(nLen);
	if (nLen > 0)
	{
		Write(szText, nLen);
	}
}

//===============================================================
// Reads a single byte from the packet.
//===============================================================
u_char CPacket::ReadByte()
{
	u_char nVal = m_pData[m_nPos];
	m_nPos++;

	return nVal;
}

//===============================================================
// Reads a short integer from the packet.
//===============================================================
u_short CPacket::ReadShort()
{
	u_short nValue = 0;
	nValue |= (m_pData[m_nPos] << 8);
	nValue |= (m_pData[m_nPos + 1]);
	m_nPos += 2;

	return nValue;
}

//===============================================================
// Reads a integer from the packet.
//===============================================================
u_int CPacket::ReadInt()
{
	u_int nValue = 0;
	nValue |= (m_pData[m_nPos]     << 24);
	nValue |= (m_pData[m_nPos + 1] << 16);
	nValue |= (m_pData[m_nPos + 2] << 8);
	nValue |= (m_pData[m_nPos + 3]);
	m_nPos += 4;

	return nValue;
}

//===============================================================
// Reads the specified amount of bytes into the specified buffer.
//===============================================================
void CPacket::ReadBytes(char *pDest, u_int nLen)
{
	memcpy(pDest, m_pData + m_nPos, nLen);
	m_nPos += nLen;
}

//===============================================================
// Reads a string from the packet into the specified buffer. Returns
// the size of the string, even when the string won't fit into the
// supplied buffer.
//===============================================================
u_int CPacket::ReadString(char *szDest, u_int nMaxLen)
{
	u_int nLen = ReadInt();
	if (nLen > 0)
	{
		u_int nSize = (nLen > nMaxLen) ? nMaxLen : nLen;
		memcpy(szDest, m_pData + m_nPos, nSize);
		szDest[nMaxLen] = 0;

		m_nPos += nLen;
	}
	return nLen;
}
